//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "DisEMBLAnalysis.h"

#include <iostream>
#include <fstream>
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define LENGHTINLINE  100000
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
DisEMBLAnalysis::DisEMBLAnalysis() {
  
  this->filename   = new String ();
  this->idpResults = new TListE <DisEMBLProcessResult> ();
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
DisEMBLAnalysis::DisEMBLAnalysis(const DisEMBLAnalysis& disEMBLAnalysis) {
  
  this->filename   = new String (disEMBLAnalysis.filename);
  this->idpResults = new TListE <DisEMBLProcessResult> (disEMBLAnalysis.idpResults);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
DisEMBLAnalysis::DisEMBLAnalysis(const DisEMBLAnalysis* disEMBLAnalysis) {
  
  this->filename   = new String (disEMBLAnalysis->filename);
  this->idpResults = new TListE <DisEMBLProcessResult> (disEMBLAnalysis->idpResults);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
DisEMBLAnalysis::~DisEMBLAnalysis() {
  
  if (this->filename)   delete this->filename;
  if (this->idpResults) delete this->idpResults;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void DisEMBLAnalysis::Filename(String* filename) {
  
  if (filename) this->filename->In(filename);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void DisEMBLAnalysis::IdpResults(TListE <DisEMBLProcessResult>* idpResults) {
  
  if (idpResults) *(this->idpResults) = *(idpResults);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* DisEMBLAnalysis::Filename(void) {
  
  return this->filename;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <DisEMBLProcessResult>* DisEMBLAnalysis::IdpResults(void) {
  
  return this->idpResults;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool DisEMBLAnalysis::ReadIDPFile(void) {
  
  if (!this->filename || !this->filename->Length()) return false;
  
  fstream fileIDPResults;
  fileIDPResults.open(this->filename->Out(), fstream::in);
  if (!fileIDPResults.is_open()) return false;
  
  char buffer[LENGHTINLINE + 1];
  int count = 0;
  
  while (!fileIDPResults.eof()) {
    
    DisEMBLProcessResult* result = new DisEMBLProcessResult ();
    
    fileIDPResults.getline(buffer, LENGHTINLINE); if (fileIDPResults.eof()) break; result->IdInput(buffer);
    fileIDPResults.getline(buffer, LENGHTINLINE); if (fileIDPResults.eof()) break; result->SequenceInput(buffer);
    fileIDPResults.getline(buffer, LENGHTINLINE); if (fileIDPResults.eof()) break; result->SeqLoopCoilsInput(buffer);
    fileIDPResults.getline(buffer, LENGHTINLINE); if (fileIDPResults.eof()) break; result->ProbLoopCoilsInput(buffer);
    fileIDPResults.getline(buffer, LENGHTINLINE); if (fileIDPResults.eof()) break; result->SeqHotLoopsInput(buffer);
    fileIDPResults.getline(buffer, LENGHTINLINE); if (fileIDPResults.eof()) break; result->ProbHotLoopsInput(buffer);
    fileIDPResults.getline(buffer, LENGHTINLINE); if (fileIDPResults.eof()) break; result->SeqRemarks465Input(buffer);
    fileIDPResults.getline(buffer, LENGHTINLINE); if (fileIDPResults.eof()) break; result->ProbRemarks465Input(buffer);
    
    this->idpResults->Add(result);
    
  }
  
  fileIDPResults.close();
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool DisEMBLAnalysis::NumberSequencePerIDPsPercernt(String* filenameOut, int range) {
  
  if (!filenameOut || !filenameOut->Length() || !this->idpResults->Length()) return false;
  
  fstream fileOut;
  
  fileOut.open(filenameOut->Out(), fstream::out);
  
  if (!fileOut.is_open()) return false;
  
  int numberPartitions = 100/range;
  
  struct tablePercent {
  
    int    range;
    int    amountIDPLoopCoils;
    int    amountIDPHotLoops;
    int    amountIDPRemarks465;
    
  };
  
  struct tablePercent listPercentAmountIDP [numberPartitions];
  
  for (int i = 0; i < numberPartitions; i++) {
    listPercentAmountIDP[i].range               = ((i + 1)*range <= 100)?((i + 1)*range):100;
    listPercentAmountIDP[i].amountIDPLoopCoils  = 0;
    listPercentAmountIDP[i].amountIDPHotLoops   = 0;
    listPercentAmountIDP[i].amountIDPRemarks465 = 0;
  }
  
  this->idpResults->SetInitial();
  while (this->idpResults->SetNext()) {
    
    double percentIDPLoopCoils  = this->idpResults->GetCurrent()->ComputePercentIDPLoopCoils();
    double percentIDPHotLoops   = this->idpResults->GetCurrent()->ComputePercentIDPHotLoops();
    double percentIDPRemarks465 = this->idpResults->GetCurrent()->ComputePercentIDPRemarks465();
    
    for (int i = 0; i < numberPartitions; i++) {
      if (percentIDPLoopCoils  >= listPercentAmountIDP[i].range) listPercentAmountIDP[i].amountIDPLoopCoils++;
      if (percentIDPHotLoops   >= listPercentAmountIDP[i].range) listPercentAmountIDP[i].amountIDPHotLoops++;
      if (percentIDPRemarks465 >= listPercentAmountIDP[i].range) listPercentAmountIDP[i].amountIDPRemarks465++;
    }    
    
  }
  
  fileOut << "------------------------------------------------------------------------------------------------------------------" << endl;
  fileOut << "|                            Results of Intrinsic Protein Disorder Prediction                                    |" << endl;
  fileOut << "------------------------------------------------------------------------------------------------------------------" << endl;
  fileOut << "|  Disordered by:   | Loops/coils definition |  Hot-loops definition  |  Remark-465 definition |                 |" << endl;
  fileOut << "-----------------------------------------------------------------------------------------------| Total Sequences |" << endl;
  fileOut << "|   % of Disorder   |  Amount  | % of Total  |  Amount  | % of Total  |  Amount  | % of Total  |                 |" << endl;
  fileOut << "------------------------------------------------------------------------------------------------------------------" << endl;
  for (int i = 0; i < numberPartitions; i++) {
    
    fileOut << "| >";
    fileOut.width(16);
    fileOut.left;
    fileOut << listPercentAmountIDP[i].range;
    fileOut << "%";
    fileOut << "|";
    
    double pIDPLoopCoils = (double)(100) * (double)(listPercentAmountIDP[i].amountIDPLoopCoils) / (double)(this->idpResults->Length());
    
    fileOut.width(10);
    fileOut.right;
    fileOut << listPercentAmountIDP[i].amountIDPLoopCoils;
    fileOut << "|";
    
    fileOut.width(13);
    fileOut.right;
    fileOut << pIDPLoopCoils;
    fileOut << "|";
    
    double pIDPHotLoops = (double)(100) * (double)(listPercentAmountIDP[i].amountIDPHotLoops) / (double)(this->idpResults->Length());
    
    fileOut.width(10);
    fileOut.right;
    fileOut << listPercentAmountIDP[i].amountIDPHotLoops;
    fileOut << "|";
    
    fileOut.width(13);
    fileOut.right;
    fileOut << pIDPHotLoops;
    fileOut << "|";
    
    double pIDPRemarks465 = (double)(100) * (double)(listPercentAmountIDP[i].amountIDPRemarks465) / (double)(this->idpResults->Length());
    
    fileOut.width(10);
    fileOut.right;
    fileOut << listPercentAmountIDP[i].amountIDPRemarks465;
    fileOut << "|";
    
    fileOut.width(13);
    fileOut.right;
    fileOut << pIDPRemarks465;
    fileOut << "|";
    
    fileOut.width(17);
    fileOut.right;
    fileOut << this->idpResults->Length();
    fileOut << "|";
    
    fileOut << endl;
    
  }
  
  fileOut << "------------------------------------------------------------------------------------------------------------------" << endl;
  
  fileOut.close();
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
